<?PHP
// vim: set expandtab tabstop=4 shiftwidth=4:
// +----------------------------------------------------------------------+
// | SAPID: XML Sapiens Engine Demonstrator                               |
// +----------------------------------------------------------------------+
// | Author:  Max Baryshnikov aka Mephius <mb@rg.by>	                  |
// | Copyright (c) 2004 Max Baryshnikov                                   |
// | http://sapid.sourceforge.net	                                      |
// +----------------------------------------------------------------------+
// | This source file is free software; you can redistribute it and/or    |
// | modify it under the terms of the GNU Lesser General Public           |
// | License as published by the Free Software Foundation; either         |
// | version 2.1 of the License, or (at your option) any later version.   |
// |                                                                      |
// | This source file is distributed in the hope that it will be useful,  |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
// | Lesser General Public License for more details.                      |
// +----------------------------------------------------------------------+
// Release: 08.09.04 (dd/mm/yy)
// $Id: tree.lib.php,v 1.4 2006/02/20 08:26:49 sheiko Exp $




class tree {
	var $pointer;
	var $prev_pointer;
	var $last_var;
	var $structure;
	var $xml_file;
	var $xml;
	var $element;
	var $element_count;
	var $default_pointer;
	var $map;
	var $depth;
	var $default_pointer_var;
	var $default_pointer_id;


	/**
	* @return tree
	* @param string $filename
	* @desc tree class constructor
	*/
	function tree($filename){
		$this->pointer="";
		$this->element="";
		$this->element_count=0;
		$this->structure=array();
		$this->map=array();
		$this->xml_file=$filename;
	}


	/**
	* @return void
	* @param XML Parser resourse ID $parser
	* @param string $name
	* @param string $attrs
	* @desc XML Parser start element handler
	*/
	function startElement($parser, $name, $attrs)
	{
		$this->depth++;
		$this->element=$name;
		if ($name=="TREEITEM") {
			$this->element_count++;
			$this->prev_pointer=$this->pointer;
			if ($attrs["VAR"]) {
				$this->pointer.="['" . $attrs["VAR"] . "']";
				$this->last_var=$attrs["VAR"];
			}else {
				$this->pointer.="['" . $name . "']";
				$this->last_var=$name;
			}
			$this->element_count=(str_replace("id_", "", $attrs["ID"])?str_replace("id_", "", $attrs["ID"]):0);
			$this->map[$this->element_count]["ID"]=$this->element_count;
			$tmp=str_replace(array("['root", "']['"), array("", "/"), $this->pointer);
			$this->map[$this->element_count]["POINTER"]=$this->pointer;
			$this->map[$this->element_count]["HREF"]=str_replace("']", "/", $tmp);
			$this->map[$this->element_count]["VAR"]=$attrs["VAR"];
			$this->map[$this->element_count]["OWNER"]=$attrs["OWNER"];
			$this->map[$this->element_count]["GROUP"]=$attrs["GROUP"];
			$this->map[$this->element_count]["PERMISSIONS"]=$attrs["PERMISSIONS"];
			@eval("\$this->structure" . $this->prev_pointer . "[\"CHILDREN\"][\"".$this->last_var."\"]=" . $this->map[$this->element_count]["ID"] . ";");
			@eval("\$this->structure" . $this->pointer . "[\"ID\"]=" . $this->map[$this->element_count]["ID"] . ";");


			$this->map[$this->element_count]["LEVEL"]=$this->depth-2;
			if ($this->map[$this->element_count]["LEVEL"]==1 and !$this->default_pointer) {
				$this->default_pointer=$this->pointer;
				$this->default_pointer_var=$attrs["VAR"];
				$this->default_pointer_id=$this->element_count;
			}
		}
	}

	/**
	* @return void
	* @param XML Parser resourse ID $parser
	* @param string $name
	* @desc XML Parser end element handler
	*/
	function endElement($parser, $name)
	{
		$this->depth--;
		if ($name=="TREEITEM") {
			$this->pointer=preg_replace("/(.*)(\['(.*)'\])$/", "\\1", $this->pointer);
		}
	}

	/**
	* @return void
	* @param XML Parser resourse ID $parser
	* @param string $data
	* @desc XML Parser data handler
	*/
	function charData($parser, $data)
	{
		if ($this->element!="TREEITEM" and trim($data)!="") {
			$this->map[$this->element_count][$this->element]=$data;
			//			if($this->element=="ID") {
			//				@eval("\$this->structure" . $this->prev_pointer . "[\"CHILDREN\"][".$this->last_var."]=" . intval($data) . ";");
			//			}
		}
		if (addslashes(trim($data))!="") eval("\$this->structure".$this->pointer."[\"".$this->element."\"]=\"".addslashes(trim($data))."\";");
	}

	/**
	* @return array
	* @desc Build tree from xml
	*/
	function build_structure(){
		
	// Tree Building Optimization 
		$treedumpfile = ROOT_PATH."usr/system/cache/structure_tree.tmp"; 
		if(file_exists($treedumpfile) AND filemtime ( $treedumpfile ) > filemtime ( $this->xml_file )) { 
		$this = unserialize(file_get_contents($treedumpfile)); 
		return $this->structure; 
		} 		
				
		$fp=@fopen($this->xml_file, "r+");
		if (!$fp) message_die("Couldn't open <b>" . $this->xml_file . "</b> for reading!");
		$size=filesize($this->xml_file);
		$this->xml=fread($fp, $size);
		fclose($fp);

		$xml_parser = xml_parser_create();
		xml_set_element_handler($xml_parser, array(&$this, "startElement"), array(&$this, "endElement"));
		xml_set_character_data_handler($xml_parser, array(&$this, "charData"));
		if (!xml_parse($xml_parser, $this->xml)) {
			message_die(sprintf("XML error: %s at line %d",
			xml_error_string(xml_get_error_code($xml_parser)),
			xml_get_current_line_number($xml_parser)));
		}
		xml_parser_free($xml_parser);
		
		// Tree Building Optimization 
		if( $fp = @fopen($treedumpfile, "w" )) { 
		fwrite($fp, serialize($this)); 
		fclose($fp); 
		} 
		
		return $this->structure;
	}

	function array2xml($tree, $depth=1){
		$xml="";
		$spacer="";
		for ($i=0; $i<$depth; $i++) $spacer.="\t";
		foreach ($tree as $key=>$value) {
			if (gettype($value)=="array" and $key!="CHILDREN") {
				$depth++;
				$xml.=$spacer . "<treeitem var=\"".$key."\" id=\"id_".$value["ID"]."\">\n" . $this->array2xml($value, $depth) . $spacer . "</treeitem>\n";
				$depth--;
			}
			elseif($key!="VAR" and $value!="" and $key!="ID") $xml.=$spacer . "<".strtolower($key).">".$value."</".strtolower($key).">\n";
		}
		return $xml;

	}

}


// If function iconv doesn't exist, provide a simple replacement using utf8.class
if(!function_exists("iconv")){
	function iconv($in_charset, $out_charset, $string){
		global $conv;
		return $string;
	}
}


?>